package com.xt.base.dao.hibernate;

import java.io.IOException;

import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;

import org.hibernate.HibernateException;
import org.hibernate.Session;
import org.hibernate.SessionFactory;


 

/**
 * 线程安全的Session提供者
 * 
 *<p> 将本类作为Filter加入web.xml后，web请求结束时系统将自动关闭Session</p>
 *<p>否则，Session使用者必须调用sessionClose()方法关闭session.</p>
 *<p><blockquote><pre>
 *try{
 *	Session session = HiberSessionHolder.getReadOnlySession();
 *	.....
 *}finally{
 *	HiberSessionHolder.closeSession();
 *}
 *</pre></blockquote><p>
 *
 * 
 * @author 杨洪波
 */
public class HiberSessionHolder implements Filter{

//	private static final org.apache.log4j.Logger 
//		log = org.apache.log4j.Logger.getLogger(SessionFactoryHolder.class);
	private static final ThreadLocal<Session> 
		session = new ThreadLocal<Session>();
	private static final ThreadLocal<ReadOnlySessionImpl> 
		readOnlySession = new ThreadLocal<ReadOnlySessionImpl>();
	private static final ThreadLocal<WritenableSessionImpl> 
		writenableSession = new ThreadLocal<WritenableSessionImpl>();
	
	synchronized private static Session getSession(){
		Session s = session.get();
		if(s == null){
			Session cs = null;
			SessionFactory sessionFactory = SessionFactoryHolder.getInstance().getSessionFactory();
			try{
				cs = getCurrentSession();
//				log.warn("next session was bind on currentConnection");
			}catch(HibernateException he){}
			s = cs == null?sessionFactory.openSession():sessionFactory.openSession(cs.connection());
			session.set(s);
//			log.warn("a new session was opened.");
		}
		return s;
	}
	
	private static Session getCurrentSession(){
		return SessionFactoryHolder.getInstance().getSessionFactory().getCurrentSession();
	}
	
	/**
	 * @return 可写的Hibernate Session,邦定在CurrentSession上.
	 **/
	public static Session getCurrentWritenableSession(){
		return new WritenableSessionImpl(getCurrentSession());
	}
	
	/**
	 *@return 只读的Hibernate Session,邦定在CurrentSession 上.
	 **/
	public static Session getCurrentReadOnlySession(){
		return new ReadOnlySessionImpl(getCurrentSession());
	}
	
	/**
	 * @return 可写的Hibernate Session,邦定在CurrentSession 的Connection上.
	 **/
	public static Session getWritenableSession(){
		WritenableSessionImpl s = writenableSession.get();
		if(s == null){
			s = new WritenableSessionImpl(getSession());
			writenableSession.set(s);
		}
		return s;
	}
	
	/**
	 * @return 只读的Hibernate Session,邦定在CurrentSession 的Connection上.
	 **/
	public static Session getReadOnlySession(){
		ReadOnlySessionImpl s = readOnlySession.get();
		if(s == null){
			s = new ReadOnlySessionImpl(getSession());
			readOnlySession.set(s);
		}
		return s;
	}
	
	/**
	 * 关闭Hibernate Session.
	 **/
	public static void closeSession(){
		WritenableSessionImpl ws = writenableSession.get();
		if(ws != null)ws.clear();
		writenableSession.set(null);
		readOnlySession.set(null);
		Session s = session.get();
		session.set(null);
		if(s != null){
			s.close();
//			log.warn("a session was closed.");
		}
//		log.warn("close session end.");
	}

	/**
	 * 清空Hibernate Session.
	 **/
	public static void clearSession(){
		Session s = session.get();
		if(s != null){
			s.clear();
//			log.warn("session was cleared.");
		}
	}
	
	/**
	 * 从Hibernate Session中清除对象
	 **/
	public static void evict(Object arg0){
		Session s = session.get();
		if(s != null && s.contains(arg0))s.evict(arg0);
	}
	
	public void destroy() {
		
	}

	public void doFilter(ServletRequest arg0, ServletResponse arg1, FilterChain arg2) throws IOException, ServletException{
		try{
			arg2.doFilter(arg0, arg1);
		}finally{
			//closeSession();
		}
	}

	public void init(FilterConfig arg0) throws ServletException {
		   
	}

}
